// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

#if ENCODER && BLOCK_ENCODER && MVEX
using System;
using Iced.Intel;
using Xunit;

namespace Iced.UnitTests.Intel.EncoderTests {
	public sealed class BlockEncoderTest64_jkcc : BlockEncoderTest {
		const int bitness = 64;
		const ulong origRip = 0x8000;
		const ulong newRip = 0x8000000000000000;
		new const DecoderOptions decoderOptions = BlockEncoderTest.decoderOptions | DecoderOptions.KNC;

		[Fact]
		void Jkcc_short_fwd() {
			var originalData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
				/*000C*/ 0xB0, 0x01,// mov al,1
				/*000E*/ 0xB0, 0x10,// mov al,10h
			};
			var newData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
				/*000C*/ 0xB0, 0x01,// mov al,1
				/*000E*/ 0xB0, 0x10,// mov al,10h
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0005,
				0x0007,
				0x000C,
				0x000E,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_short_bwd() {
			var originalData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC4, 0xE0, 0x50, 0x74, 0xF9,// jkzd k5, short 0
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC4, 0xE0, 0x50, 0x75, 0xF2,// jknzd k5, short 0
				/*000E*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC4, 0xE0, 0x50, 0x74, 0xF9,// jkzd k5, short 0
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC4, 0xE0, 0x50, 0x75, 0xF2,// jknzd k5, short 0
				/*000E*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0002,
				0x0007,
				0x0009,
				0x000E,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_short_other_short() {
			var originalData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
				/*000C*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x0A,// jkzd k5, short 0Eh
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x03,// jknzd k5, short 0Eh
				/*000C*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0005,
				0x0007,
				0x000C,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, origRip - 1, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_short_other_near() {
			var originalData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
				/*000C*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x07, 0xF0, 0xFF, 0xFF,// jkzd k5, near ptr 0Eh
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0xFE, 0xEF, 0xFF, 0xFF,// jknzd k5, near ptr 0Eh
				/*0010*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0007,
				0x0009,
				0x0010,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, origRip + 0x1000, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_short_other_long() {
			var originalData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x0B,// jkzd k5, short 10h
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x05,// jknzd k5, short 11h
				/*000C*/ 0xB0, 0x01,// mov al,1
				/*000E*/ 0x90,// nop
			};
			var newData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x75, 0x06,// jknzd k5, short 8
				/*0005*/ 0xFF, 0x25, 0x15, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000020h]
				/*000B*/ 0xB0, 0x00,// mov al,0
				/*000D*/ 0xC4, 0xE0, 0x50, 0x74, 0x06,// jkzd k5, short 12
				/*0012*/ 0xFF, 0x25, 0x10, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000028h]
				/*0018*/ 0xB0, 0x01,// mov al,1
				/*001A*/ 0x90,// nop
				/*001B*/ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
				/*0020*/ 0x10, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
				/*0028*/ 0x11, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
			};
			var expectedInstructionOffsets = new uint[] {
				uint.MaxValue,
				0x000B,
				uint.MaxValue,
				0x0018,
				0x001A,
			};
			var expectedRelocInfos = new RelocInfo[] {
				new RelocInfo(RelocKind.Offset64, 0x8000000000000020),
				new RelocInfo(RelocKind.Offset64, 0x8000000000000028),
			};
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			const ulong origRip = 0x123456789ABCDE00;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_fwd_short() {
			var originalData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 12h
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 12h
				/*0010*/ 0xB0, 0x01,// mov al,1
				/*0012*/ 0xB0, 0x10,// mov al,10h
			};
			var newData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
				/*0005*/ 0xB0, 0x00,// mov al,0
				/*0007*/ 0xC4, 0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
				/*000C*/ 0xB0, 0x01,// mov al,1
				/*000E*/ 0xB0, 0x10,// mov al,10h
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0005,
				0x0007,
				0x000C,
				0x000E,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_fwd_near() {
			var originalData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x8D, 0x00, 0x00, 0x00,// jkzd k5, near ptr 94h
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0x84, 0x00, 0x00, 0x00,// jknzd k5, near ptr 94h
				/*0010*/ 0xB0, 0x01,// mov al,1
				/*0012*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*001F*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*002C*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0039*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0046*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0053*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0060*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*006D*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*007A*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0087*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0094*/ 0xB0, 0x10,// mov al,10h
			};
			var newData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x8D, 0x00, 0x00, 0x00,// jkzd k5, near ptr 94h
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0x84, 0x00, 0x00, 0x00,// jknzd k5, near ptr 94h
				/*0010*/ 0xB0, 0x01,// mov al,1
				/*0012*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*001F*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*002C*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0039*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0046*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0053*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0060*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*006D*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*007A*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0087*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0094*/ 0xB0, 0x10,// mov al,10h
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0007,
				0x0009,
				0x0010,
				0x0012,
				0x001F,
				0x002C,
				0x0039,
				0x0046,
				0x0053,
				0x0060,
				0x006D,
				0x007A,
				0x0087,
				0x0094,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_bwd_short() {
			var originalData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC5, 0xD0, 0x84, 0xF7, 0xFF, 0xFF, 0xFF,// jkzd k5, near ptr 0
				/*0009*/ 0xB0, 0x00,// mov al,0
				/*000B*/ 0xC5, 0xD0, 0x85, 0xEE, 0xFF, 0xFF, 0xFF,// jknzd k5, near ptr 0
				/*0012*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC4, 0xE0, 0x50, 0x74, 0xF9,// jkzd k5, short 0
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC4, 0xE0, 0x50, 0x75, 0xF2,// jknzd k5, short 0
				/*000E*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0002,
				0x0007,
				0x0009,
				0x000E,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_bwd_near() {
			var originalData = new byte[] {
				/*0000*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*000D*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*001A*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0027*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0034*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0041*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*004E*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*005B*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0068*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0075*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0082*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*008F*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*009C*/ 0xC5, 0xD0, 0x84, 0x5D, 0xFF, 0xFF, 0xFF,// jkzd k5, near ptr 0
				/*00A3*/ 0xB0, 0x00,// mov al,0
				/*00A5*/ 0xC5, 0xD0, 0x85, 0x54, 0xFF, 0xFF, 0xFF,// jknzd k5, near ptr 0
				/*00AC*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*000D*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*001A*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0027*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0034*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0041*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*004E*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*005B*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0068*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0075*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*0082*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*008F*/ 0x64, 0x67, 0xC7, 0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
				/*009C*/ 0xC5, 0xD0, 0x84, 0x5D, 0xFF, 0xFF, 0xFF,// jkzd k5, near ptr 0
				/*00A3*/ 0xB0, 0x00,// mov al,0
				/*00A5*/ 0xC5, 0xD0, 0x85, 0x54, 0xFF, 0xFF, 0xFF,// jknzd k5, near ptr 0
				/*00AC*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x000D,
				0x001A,
				0x0027,
				0x0034,
				0x0041,
				0x004E,
				0x005B,
				0x0068,
				0x0075,
				0x0082,
				0x008F,
				0x009C,
				0x00A3,
				0x00A5,
				0x00AC,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_other_short() {
			var originalData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC5, 0xD0, 0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 14h
				/*0009*/ 0xB0, 0x00,// mov al,0
				/*000B*/ 0xC5, 0xD0, 0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 14h
				/*0012*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC4, 0xE0, 0x50, 0x74, 0x0E,// jkzd k5, short 0
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC4, 0xE0, 0x50, 0x75, 0x07,// jknzd k5, short 0
				/*000E*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0002,
				0x0007,
				0x0009,
				0x000E,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, origRip - 1, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_other_near() {
			var originalData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC5, 0xD0, 0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 14h
				/*0009*/ 0xB0, 0x00,// mov al,0
				/*000B*/ 0xC5, 0xD0, 0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 14h
				/*0012*/ 0xB0, 0x01,// mov al,1
			};
			var newData = new byte[] {
				/*0000*/ 0xB0, 0x10,// mov al,10h
				/*0002*/ 0xC5, 0xD0, 0x84, 0x0B, 0xF0, 0xFF, 0xFF,// jkzd k5, near ptr 14h
				/*0009*/ 0xB0, 0x00,// mov al,0
				/*000B*/ 0xC5, 0xD0, 0x85, 0x02, 0xF0, 0xFF, 0xFF,// jknzd k5, near ptr 14h
				/*0012*/ 0xB0, 0x01,// mov al,1
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0002,
				0x0009,
				0x000B,
				0x0012,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			EncodeBase(bitness, origRip, originalData, origRip + 0x1000, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_other_long() {
			var originalData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x0C, 0x00, 0x00, 0x00,// jkzd k5, near ptr 13h
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0x04, 0x00, 0x00, 0x00,// jknzd k5, near ptr 14h
				/*0010*/ 0xB0, 0x01,// mov al,1
				/*0012*/ 0x90,// nop
			};
			var newData = new byte[] {
				/*0000*/ 0xC4, 0xE0, 0x50, 0x75, 0x06,// jknzd k5, short 0Bh
				/*0005*/ 0xFF, 0x25, 0x15, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000020h]
				/*000B*/ 0xB0, 0x00,// mov al,0
				/*000D*/ 0xC4, 0xE0, 0x50, 0x74, 0x06,// jkzd k5, short 18h
				/*0012*/ 0xFF, 0x25, 0x10, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000028h]
				/*0018*/ 0xB0, 0x01,// mov al,1
				/*001A*/ 0x90,// nop
				/*001B*/ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
				/*0020*/ 0x13, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
				/*0028*/ 0x14, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
			};
			var expectedInstructionOffsets = new uint[] {
				uint.MaxValue,
				0x000B,
				uint.MaxValue,
				0x0018,
				0x001A,
			};
			var expectedRelocInfos = new RelocInfo[] {
				new RelocInfo(RelocKind.Offset64, 0x8000000000000020),
				new RelocInfo(RelocKind.Offset64, 0x8000000000000028),
			};
			const BlockEncoderOptions options = BlockEncoderOptions.None;
			const ulong origRip = 0x123456789ABCDE00;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}

		[Fact]
		void Jkcc_near_fwd_short_no_opt() {
			var originalData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 12h
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 12h
				/*0010*/ 0xB0, 0x01,// mov al,1
				/*0012*/ 0xB0, 0x10,// mov al,10h
			};
			var newData = new byte[] {
				/*0000*/ 0xC5, 0xD0, 0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 12h
				/*0007*/ 0xB0, 0x00,// mov al,0
				/*0009*/ 0xC5, 0xD0, 0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 12h
				/*0010*/ 0xB0, 0x01,// mov al,1
				/*0012*/ 0xB0, 0x10,// mov al,10h
			};
			var expectedInstructionOffsets = new uint[] {
				0x0000,
				0x0007,
				0x0009,
				0x0010,
				0x0012,
			};
			var expectedRelocInfos = Array.Empty<RelocInfo>();
			const BlockEncoderOptions options = BlockEncoderOptions.DontFixBranches;
			EncodeBase(bitness, origRip, originalData, newRip, newData, options, decoderOptions, expectedInstructionOffsets, expectedRelocInfos);
		}
	}
}
#endif
